package com.example.androidaudiovideodemo.activity

import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.graphics.Camera
import android.graphics.Color
import android.graphics.ImageFormat
import android.graphics.SurfaceTexture
import android.hardware.camera2.*
import android.hardware.camera2.params.OutputConfiguration
import android.hardware.camera2.params.SessionConfiguration
import android.media.ImageReader
import android.os.Build
import android.os.Handler
import android.os.HandlerThread
import android.util.Log
import android.util.Size
import android.view.Surface
import android.view.SurfaceHolder
import android.view.TextureView
import androidx.core.app.ActivityCompat
import com.blankj.utilcode.util.FileUtils
import com.blankj.utilcode.util.PermissionUtils
import com.blankj.utilcode.util.SDCardUtils
import com.blankj.utilcode.util.ToastUtils
import com.example.androidaudiovideodemo.R
import com.example.androidaudiovideodemo.base.BaseActivity
import kotlinx.android.synthetic.main.activity_video_collection_and_preview.*
import java.io.File
import java.io.FileOutputStream
import java.lang.Exception
import java.util.concurrent.Executor
import kotlin.concurrent.thread

/**
 *
 * author: renbing
 *
 * date: 2021/12/23
 *
 * des: 3. 在 Android 平台使用 Camera API 进行视频的采集，分别使用 SurfaceView、TextureView 来预览 Camera 数据，取到 NV21 的数据回调
 */
class VideoCollectionAndPreviewActivity : BaseActivity(){

    private var mCameraManager: CameraManager? = null
    private var mImageReader: ImageReader? = null
    private var mImageReaderPicture: ImageReader? = null
    private var mCameraDevice: CameraDevice? = null
    private var mCameraCaptureSession: CameraCaptureSession? = null
    private var mCameraId = "0"
    private var mCameraCharacteristics: CameraCharacteristics? = null
    private var mCameraSensorOrientation = 0 //摄像头方向
    private var mCameraFacing = CameraCharacteristics.LENS_FACING_BACK //默认使用后置摄像头
    private var mDisplayRotation = 0
    private var mIsRecording = false
    private var mCameraHandler: Handler? = null
    private val mHandlerThread = HandlerThread("camera_thread")

    private var mPreviewSize: Size = Size(720,1280)
    private var mSavePicSize: Size = Size(720,1280)

    override fun getLayoutId(): Int = R.layout.activity_video_collection_and_preview

    override fun performInit() {
        super.performInit()

        setStatusBarColor(this,true)
    }

    override fun onRestart() {
        super.onRestart()

        Log.e("TAG","onRestart")
        initCameraInfo()
        openCamera(0)
    }

    override fun initData() {
        super.initData()

        mHandlerThread.start()
        mCameraHandler = Handler(mHandlerThread.looper)
        mDisplayRotation = windowManager.defaultDisplay.rotation

        mCameraManager = getSystemService(Context.CAMERA_SERVICE) as CameraManager

        task_three_title_view.run {
            setLeftIconColorFilter(Color.BLACK)
            setOnLeftIconClickListener {
                finish()
            }
        }

        preview_texture_view.surfaceTextureListener = object : TextureView.SurfaceTextureListener{
            override fun onSurfaceTextureAvailable(
                surface: SurfaceTexture,
                width: Int,
                height: Int
            ) {
                initCameraInfo()
            }

            override fun onSurfaceTextureSizeChanged(
                surface: SurfaceTexture,
                width: Int,
                height: Int
            ) {

            }

            override fun onSurfaceTextureDestroyed(surface: SurfaceTexture): Boolean {
                releaseCamera()
                return true
            }

            override fun onSurfaceTextureUpdated(surface: SurfaceTexture) {

            }

        }

        preview_surface_view.holder.addCallback(object : SurfaceHolder.Callback{
            override fun surfaceCreated(holder: SurfaceHolder) {
//                initCameraInfo()
            }

            override fun surfaceChanged(
                holder: SurfaceHolder,
                format: Int,
                width: Int,
                height: Int
            ) {

            }

            override fun surfaceDestroyed(holder: SurfaceHolder) {
                releaseCamera()
            }

        })
    }

    override fun initListener() {
        super.initListener()

        start_video_record.setOnClickListener {
            if (mIsRecording) return@setOnClickListener
            if (mCameraCaptureSession == null){
                initCameraInfo()
            }
            openCamera(0)
        }

        stop_video_record.setOnClickListener {
            if (!mIsRecording) return@setOnClickListener
            ToastUtils.showShort("已关闭摄像头")
            mIsRecording = false
            releaseCamera()
        }

        change_camera.setOnClickListener {
            if (!mIsRecording) {
                ToastUtils.showShort("请先打开摄像头")
                return@setOnClickListener
            }
            mCameraFacing = if (mCameraFacing == CameraCharacteristics.LENS_FACING_BACK) CameraCharacteristics.LENS_FACING_FRONT else CameraCharacteristics.LENS_FACING_BACK
            releaseCamera()
            initCameraInfo()
            openCamera(if (mCameraFacing == CameraCharacteristics.LENS_FACING_BACK) 1 else 2)
        }

        take_photo.setOnClickListener {
            if (!mIsRecording) {
                ToastUtils.showShort("请先打开摄像头")
                return@setOnClickListener
            }
            takePicture()
        }
    }

    /**
     * 初始化Camera
     */
    private fun initCameraInfo() {
        //获取相机服务
        mCameraManager = getSystemService(Context.CAMERA_SERVICE) as CameraManager
        //获取摄像头列表
        val cameraIdList = mCameraManager?.cameraIdList
        if (cameraIdList?.isEmpty() == true){
            ToastUtils.showShort("没有可用的相机")
            return
        }
        //确定需开启的摄像头
        cameraIdList?.forEach {
            val cameraCharacteristics = mCameraManager?.getCameraCharacteristics(it)
            val facing = cameraCharacteristics?.get(CameraCharacteristics.LENS_FACING)
            if (facing == mCameraFacing){
                mCameraId = it
                mCameraCharacteristics = cameraCharacteristics
                Log.e("TAG","调用${if (mCameraId == "0") "后置" else "前置"}摄像头")
            }
        }
        val supportLevel = mCameraCharacteristics?.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL)
        if (supportLevel == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY){
            ToastUtils.showShort("相机硬件不支持新特性")
        }
        mCameraSensorOrientation = mCameraCharacteristics?.get(CameraCharacteristics.SENSOR_ORIENTATION)?:0
        Log.e("TAG","摄像头方向：$mCameraSensorOrientation")
        val configurationMap = mCameraCharacteristics?.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
        val savePicSize = configurationMap?.getOutputSizes(ImageFormat.JPEG)
        val previewSize = configurationMap?.getOutputSizes(SurfaceTexture::class.java)

//        val exchange = exchangeWidthAndHeight(mDisplayRotation,mCameraSensorOrientation)

        preview_texture_view.surfaceTexture?.setDefaultBufferSize(mPreviewSize.width,mPreviewSize.height)

        //预览ImageReader  获取数据回调
        mImageReader = ImageReader.newInstance(mPreviewSize.width,mPreviewSize.height,ImageFormat.YUV_420_888,2)
        //拍照ImageReader
        mImageReaderPicture = ImageReader.newInstance(mPreviewSize.width,mPreviewSize.height,ImageFormat.JPEG,1)
        mImageReader?.setOnImageAvailableListener({
            val image = it.acquireLatestImage()
            Log.e("TAG","${image.format}")
            Log.e("TAG","U_ROW_STRIDE:${image.planes[1].rowStride}-----V_ROW_STRIDE:${image.planes[2].rowStride}")
            Log.e("TAG","U_PIXEL_STRIDE:${image.planes[1].pixelStride}-----V_PIXEL_STRIDE:${image.planes[2].pixelStride}")
            //image一定要关掉  不然下一帧数据会进不来（根据你设置的maxImages） 虽然acquireLastestImage方法中会close掉， 但无效还是需要自己调一次
            //notice： 是image.close() 不是it.close()
            image.close()
        },mCameraHandler)
        mImageReaderPicture?.setOnImageAvailableListener({
            val image = it.acquireLatestImage()
            val byteBuffer = image.planes[0].buffer
            val byteArray = ByteArray(byteBuffer.remaining())
            byteBuffer.get(byteArray)
            image.close()
            val proRootFile = FileUtils.getFileByPath("${SDCardUtils.getSDCardPathByEnvironment()}/$packageName")
            if (!proRootFile.exists()){
                proRootFile.mkdirs()
            }
            val screenShotDir = File(proRootFile,"screenshot")
            if (!screenShotDir.exists()){
                screenShotDir.mkdir()
            }
            val screenShotFile = File(screenShotDir,"screenshot_${System.currentTimeMillis()}.jpg")
            if (!screenShotFile.exists()){
                screenShotFile.createNewFile()
            }
            val fos: FileOutputStream
            try {
                fos = FileOutputStream(screenShotFile)
                fos.write(byteArray)
                fos.flush()
                fos.close()
                ToastUtils.showShort("图片已保存至：${screenShotFile.absolutePath}")
            }catch (e: Exception){
                e.printStackTrace()
            }
        },mCameraHandler)
    }

    private fun openCamera(tag: Int){
        if (ActivityCompat.checkSelfPermission(this@VideoCollectionAndPreviewActivity, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            PermissionUtils.permission(Manifest.permission.CAMERA).callback(object : PermissionUtils.SimpleCallback{
                override fun onGranted() {
                    openCamera(tag)
                }

                override fun onDenied() {
                    ToastUtils.showShort("未获取到摄像头权限，取消操作")
                }

            }).request()
        }else{
            mCameraManager?.openCamera(mCameraId,object : CameraDevice.StateCallback(){
                override fun onOpened(camera: CameraDevice) {
                    mIsRecording = true
                    when(tag){
                        0 -> ToastUtils.showShort("已开启摄像头")
                        1 -> ToastUtils.showShort("已切换至后置摄像头")
                        2 -> ToastUtils.showShort("已切换至前置摄像头")
                    }
                    mCameraDevice = camera
                    createCaptureSession(camera)
                }

                override fun onDisconnected(camera: CameraDevice) {

                }

                override fun onError(camera: CameraDevice, error: Int) {
                    ToastUtils.showShort("摄像头开启失败")
                }

            },mCameraHandler)

        }

    }

    /**
     * 创建会话
     * 实现预览、录像、截屏等操作
     */
    private fun createCaptureSession(cameraDevice: CameraDevice){
        val captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW) //预览请求

        val surfaceTextureView = Surface(preview_texture_view.surfaceTexture)
        val surfaceSurfaceView = preview_surface_view.holder.surface
        captureRequestBuilder.run {
            addTarget(surfaceTextureView)// TextureView预览
            addTarget(surfaceSurfaceView)// SurfaceVIew预览
            addTarget(mImageReader?.surface!!)//通过ImageReader获取到视频帧数据
            set(CaptureRequest.CONTROL_AE_MODE,CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH)// 闪光灯
            set(CaptureRequest.CONTROL_AE_MODE,CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE)// 自动对焦
        }
//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P){
//            val sessionConfiguration = SessionConfiguration(
//                SessionConfiguration.SESSION_HIGH_SPEED,
//                arrayListOf(
//                    OutputConfiguration(surfaceTextureView),
//                    OutputConfiguration(surfaceSurfaceView),
//                    OutputConfiguration(mImageReader?.surface!!)
//                ),
//                { },
//                object : CameraCaptureSession.StateCallback() {
//                    override fun onConfigured(session: CameraCaptureSession) {
//                        mCameraCaptureSession = session
//                        session.setRepeatingRequest(captureRequestBuilder.build(),
//                            object : CameraCaptureSession.CaptureCallback() {
//                                override fun onCaptureCompleted(
//                                    session: CameraCaptureSession,
//                                    request: CaptureRequest,
//                                    result: TotalCaptureResult
//                                ) {
//                                    super.onCaptureCompleted(session, request, result)
//
//                                }
//
//                                override fun onCaptureFailed(
//                                    session: CameraCaptureSession,
//                                    request: CaptureRequest,
//                                    failure: CaptureFailure
//                                ) {
//                                    super.onCaptureFailed(session, request, failure)
//                                    ToastUtils.showShort("开启预览失败")
//                                }
//                            },mCameraHandler)
//                    }
//
//                    override fun onConfigureFailed(session: CameraCaptureSession) {
//
//                    }
//                })
//            cameraDevice.createCaptureSession(sessionConfiguration)
//        }else{
            cameraDevice.createCaptureSession(arrayListOf(surfaceTextureView,surfaceSurfaceView,mImageReader?.surface,mImageReaderPicture?.surface),object : CameraCaptureSession.StateCallback(){
                override fun onConfigured(session: CameraCaptureSession) {
                    mCameraCaptureSession = session
                    // 一直发送预览请求
                    session.setRepeatingRequest(captureRequestBuilder.build(),null,mCameraHandler)
                }

                override fun onConfigureFailed(session: CameraCaptureSession) {
                    ToastUtils.showShort("开启预览会话失败")
                }

            },mCameraHandler)
//        }
    }

    /**
     * 拍照
     */
    private fun takePicture(){
        if (!mIsRecording){
            ToastUtils.showShort("请先开启摄像头")
            return
        }
        mCameraDevice?.run {
            val captureRequestBuilder = createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE)
            captureRequestBuilder.run {
                addTarget(mImageReaderPicture?.surface!!)
                set(CaptureRequest.CONTROL_AE_MODE,CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE)//自动对焦
                set(CaptureRequest.CONTROL_AE_MODE,CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH)//闪光灯
                set(CaptureRequest.JPEG_ORIENTATION,mCameraSensorOrientation)
            }
            mCameraCaptureSession?.capture(captureRequestBuilder.build(),null,mCameraHandler)
        }
    }

    private fun releaseCamera(){
        mCameraCaptureSession?.close()
        mCameraCaptureSession = null

        mCameraDevice?.close()
        mCameraDevice = null

        mImageReader?.close()
        mImageReader = null

        mImageReaderPicture?.close()
        mImageReaderPicture = null
    }

    override fun onPause() {
        super.onPause()

        releaseCamera()
    }

    override fun onDestroy() {
        super.onDestroy()

        mHandlerThread.quitSafely()
    }
}